home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 22
/
Cream of the Crop 22.iso
/
os2
/
ext2_200.zip
/
EXT2_SRC.ZIP
/
32BITS
/
EXT2-OS2
/
EXT2FLT
/
E2ROUTER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-01-24
|
8KB
|
199 lines
/************************************************************************/
/* Linux partition filter. */
/* (C) Copyright Deon van der Westhuysen, July 1995. */
/* */
/* Dedicated to Jesus Christ, my Lord and Saviour. */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2, or (at your option) */
/* any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* */
/* This code is still under development; expect some rough edges. */
/* */
/************************************************************************/
#include "debug.h"
#include "e2data.h"
#include "e2router.h"
#include "e2wrap.h"
#include "e2filt.h"
#include "e2part.h"
/* Macro to test whether an pointer points to an element in the array */
#define IS_ELEMENT(PTR,ARRAY,SIZE) ((((VOID*)PTR)>=((VOID*)ARRAY))&&\
(((VOID*)PTR)<((VOID*)(ARRAY+SIZE))))
/* All IORBs arrive here. We queue the IORB and then call the queue server */
/* to take over. */
void E2FilterIORB (PIORB pIORB)
{
NPRecHeader pUnitRec; /* Ptr to unit rec for IORB */
NPIORBQueue pQueue; /* Ptr to queue for IORB */
if (pIORB->CommandCode==IOCC_CONFIGURATION) /* For configuration IORBs: */
pUnitRec= (NPRecHeader) VirtUnits; /* Assign IORB to the first */
/* virtual unit. (For queue) */
else
pUnitRec= (NPRecHeader) pIORB->UnitHandle; /* Get pointer to unit */
/* from the unit handle */
/* Check to see if pUnitRec is a pointer to a valid unit record. */
if (!(IS_ELEMENT(pUnitRec,BaseUnits,NumBaseUnits)||
IS_ELEMENT(pUnitRec,VirtUnits,NumVirtUnits)))
{
IORBError (pIORB,IOERR_NO_SUCH_UNIT); /* Tell them they are crazy! */
NotifyDone (pIORB); /* Notify that we are done */
}
else
{
pQueue= &(pUnitRec->IORBQueue); /* Get pointer to IORB queue */
DISABLE /* Same safety... */
AddIORBToQueue (pQueue,pIORB); /* Add IORB to queue */
ENABLE /* Re-enable interrupts */
StartIORBQueue (pQueue); /* Try to restart the queue */
}
}
/* Function to add an IORB to a queue of IORBs maintainded for the unit. */
/* MUST be called with interrupts disabled. */
void AddIORBToQueue (NPIORBQueue pQueue, PIORB pIORB)
{
if (pQueue->pTail) /* Queue had IORBs waiting: */
pQueue->pTail->pNxtIORB= pIORB; /* Add IORB into queue */
else /* Queue was empty: */
pQueue->pHead= pIORB; /* Add IORB into queue */
while (pIORB->RequestControl&IORB_CHAIN) /* If not last IORB in chain */
pIORB= pIORB->pNxtIORB; /* Seek next IORB in request */
(pQueue->pTail= pIORB)->pNxtIORB= 0; /* Set new tail pointer and */
/* clear ptr to chained IORB */
}
/* Function retrieve an IORB from the queue. Returns NULL if the queue was */
/* empty. MUST be called with interrupts disabled. */
PIORB GetIORBFromQueue (NPIORBQueue pQueue)
{
PIORB pReturnIORB; /* Pointer to return */
if (pQueue->pHead) /* If queue is not empty: */
{
pReturnIORB= pQueue->pHead; /* Get pointer to head */
pQueue->pHead= pReturnIORB->pNxtIORB; /* Update the head pointer */
if (!pQueue->pHead) /* If queue now is empty: */
pQueue->pTail= NULL; /* Clear the tail pointer */
}
else
pReturnIORB= NULL; /* Queue empty: return NULL */
return pReturnIORB;
}
/* Function to service an IORB queue. It first checks that the queue is not */
/* being serviced before entering the service loop. */
void StartIORBQueue (NPIORBQueue pQueue)
{
PIORB pIORB; /* Ptr to IORB to execute */
NPRecHeader pUnitRec; /* Pointer to unit record */
DISABLE
if (!(pQueue->Flags&F_SERVER_ACTIVE)) /* Check to no one is busy */
/* servicing this queue */
{
pQueue->Flags|=F_SERVER_ACTIVE; /* Grap control of queue */
/* If we get where we have exclusize access to the queue. */
while ((!(pQueue->Flags&F_REQUEST_BUSY))&&
((pIORB= GetIORBFromQueue (pQueue))!=NULL))
/* Loop while there is an */
/* IORB ready to be serviced */
/* and the previous IORB is */
/* finished. */
{
pQueue->Flags|=F_REQUEST_BUSY; /* Show request in progress */
ENABLE
if (pIORB->CommandCode==IOCC_CONFIGURATION) /* For configuration IORBs: */
pUnitRec= (NPRecHeader) VirtUnits; /* Assign IORB to the first */
/* virtual unit. (For queue) */
else
pUnitRec= (NPRecHeader) pIORB->UnitHandle; /* Get pointer to unit */
/* from the unit handle */
/* We will handle (de)allocation and allocation checks here since it is */
/* common between the two parts- filter and virtual units. */
if (pIORB->CommandCode==IOCC_UNIT_CONTROL) /* Unit control command? */
{
if (pIORB->CommandModifier==IOCM_ALLOCATE_UNIT)
{ /* Allocate unit??? */
if (pUnitRec->Flags&F_ALLOCATED)
IORBError (pIORB,IOERR_UNIT_ALLOCATED); /* Error if allocated */
else
pUnitRec->Flags|=F_ALLOCATED; /* Else allocate the unit */
pQueue->Flags&=~F_REQUEST_BUSY; /* Indicate queue finished */
NotifyDone (pIORB);
continue; /* Service next request */
}
if (pIORB->CommandModifier==IOCM_DEALLOCATE_UNIT)
{ /* Deallocate unit??? */
if (!(pUnitRec->Flags&F_ALLOCATED))
IORBError (pIORB,IOERR_UNIT_NOT_ALLOCATED);
/* Error if not allocated */
else
pUnitRec->Flags&=~F_ALLOCATED; /* Else deallocate unit */
pQueue->Flags&=~F_REQUEST_BUSY; /* Indicate queue finished */
NotifyDone (pIORB);
continue; /* Service next request */
}
}
/* Do allocations checks... if notify points to us, skip check. */
if (!(pUnitRec->Flags&F_ALLOCATED)) /* If unit is not allocated: */
if (pIORB->NotifyAddress!=&PartNotifyWrapper)
/* and we didn't make request */
if (pIORB->CommandCode!=IOCC_CONFIGURATION)
/* and not configuration */
{
IORBError (pIORB,IOERR_UNIT_NOT_ALLOCATED);
/* Then it is an error */
pQueue->Flags&=~F_REQUEST_BUSY; /* Indicate queue finished */
NotifyDone (pIORB);
continue; /* Service next request */
}
if (IS_ELEMENT(pUnitRec,BaseUnits,NumBaseUnits))
FilterHandler (pIORB); /* Handler for base units */
else if (IS_ELEMENT(pUnitRec,VirtUnits,NumVirtUnits))
PartHandler (pIORB); /* Handler for virtual units */
DISABLE
}
/* Tell others that this server is not active any more... */
pQueue->Flags&=~F_SERVER_ACTIVE;
}
ENABLE
}
/* Notify client that the IORB processing is completed. */
void NotifyDone (PIORB pIORB)
{
pIORB->Status |= IORB_DONE; /* Set 'DONE' flag */
if (pIORB->RequestControl&IORB_ASYNC_POST) /* If notify flag set... */
pIORB->NotifyAddress(pIORB); /* Notify the caller */
}
/* Function to return an error code via IORB */
void IORBError (PIORB pIORB, USHORT ErrorCode)
{
if (ErrorCode) /* If really an error: */
{
pIORB->Status |= IORB_ERROR; /* Set error flag */
pIORB->ErrorCode= ErrorCode; /* Fill in error code field */
}
}